package org.jeecg.modules.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.wms.entity.WmsWarehouse;
import org.jeecg.modules.wms.entity.WmsWarehouseLocation;
import org.jeecg.modules.wms.mapper.WmsWarehouseLocationMapper;
import org.jeecg.modules.wms.mapper.WmsWarehouseMapper;
import org.jeecg.modules.wms.service.IAutoLocationAllocationService;
import org.jeecg.modules.wms.service.IWmsMaterialService;
import org.jeecg.modules.wms.entity.WmsMaterial;
import org.jeecg.modules.wms.vo.SurplusMaterialVO;
import org.jeecg.modules.wms.vo.WmsInboundOrderMaterialVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自动库位分配服务实现类
 */
@Slf4j
@Service
public class AutoLocationAllocationServiceImpl implements IAutoLocationAllocationService {
    
    @Autowired
    private WmsWarehouseMapper warehouseMapper;
    
    @Autowired
    private WmsWarehouseLocationMapper locationMapper;
    
    @Autowired
    private org.jeecg.modules.wms.config.SurplusInboundConfig surplusInboundConfig;
    
    @Autowired
    private IWmsMaterialService materialService;
    
    @Override
    public List<WmsInboundOrderMaterialVO> allocateLocationsForSurplus(List<SurplusMaterialVO> surplusMaterials) {
        if (surplusMaterials == null || surplusMaterials.isEmpty()) {
            return new ArrayList<>();
        }
        
        try {
            log.info("开始为{}个余料分配库位", surplusMaterials.size());
            
            List<WmsInboundOrderMaterialVO> materialVOList = new ArrayList<>();
            
            for (SurplusMaterialVO surplusMaterial : surplusMaterials) {
                try {
                    WmsInboundOrderMaterialVO materialVO = allocateLocationForSingleSurplus(surplusMaterial);
                    if (materialVO != null) {
                        materialVOList.add(materialVO);
                    }
                } catch (Exception e) {
                    log.error("为余料[{}]分配库位失败", surplusMaterial.getMaterialCode(), e);
                    
                    // 根据配置的处理策略决定如何处理失败
                    if ("strict".equals(surplusInboundConfig.getAllocationFailureStrategy())) {
                        // 严格模式：抛出异常，中断整个流程
                        throw new JeecgBootException("余料库位分配失败: " + e.getMessage());
                    } else {
                        // 宽松模式：跳过该余料，继续处理下一个
                        log.warn("宽松模式下跳过余料[{}]的库位分配", surplusMaterial.getMaterialCode());
                    }
                }
            }
            
            log.info("余料库位分配完成，成功分配: {}/{}", materialVOList.size(), surplusMaterials.size());
            return materialVOList;
            
        } catch (Exception e) {
            log.error("批量分配余料库位失败", e);
            throw new JeecgBootException("批量分配余料库位失败: " + e.getMessage());
        }
    }
    
    @Override
    public WmsInboundOrderMaterialVO allocateLocationForSingleSurplus(SurplusMaterialVO surplusMaterial) {
        try {
            log.debug("开始为余料[{}]分配库位", surplusMaterial.getMaterialCode());
            
            // 1. 获取余料专用仓库列表
            List<String> surplusWarehouseIds = getSurplusWarehouseIds();
            
            String selectedWarehouseId = null;
            String selectedLocationId = null;
            String selectedWarehouseName = null;
            String selectedLocationName = null;
            
            // 2. 优先在余料专用仓库中查找可用库位
            for (String warehouseId : surplusWarehouseIds) {
                List<String> availableLocationIds = getAvailableLocationIds(warehouseId, "5"); // 余料类型
                if (!availableLocationIds.isEmpty()) {
                    selectedWarehouseId = warehouseId;
                    selectedLocationId = availableLocationIds.get(0); // 选择第一个可用库位
                    break;
                }
            }
            
            // 4. 如果仍然没有找到可用库位，抛出异常
            if (selectedWarehouseId == null || selectedLocationId == null) {
                log.warn("未找到可用库位用于余料: {}", surplusMaterial.getMaterialCode());
                throw new JeecgBootException("未找到可用库位用于余料: " + surplusMaterial.getMaterialCode());
            }
            
            // 5. 获取仓库和库位名称
            WmsWarehouse selectedWarehouse = warehouseMapper.selectById(selectedWarehouseId);
            WmsWarehouseLocation selectedLocation = locationMapper.selectById(selectedLocationId);
            
            if (selectedWarehouse != null) {
                selectedWarehouseName = selectedWarehouse.getWarehouseName();
            }
            if (selectedLocation != null) {
                selectedLocationName = selectedLocation.getLocationName();
            }
            
            // 6. 创建入库物料VO
            WmsInboundOrderMaterialVO materialVO = new WmsInboundOrderMaterialVO();
            materialVO.setMaterialCode(surplusMaterial.getMaterialCode());//余料编号
            materialVO.setMaterialName(surplusMaterial.getProfileName());
            materialVO.setMaterialType(5); // 余料类型
            materialVO.setSpecification(surplusMaterial.getSpecification());
            
            // 通过源型材编码获取颜色信息
            String sourceProfileCode = surplusMaterial.getProfileCode();
            if (StringUtils.isNotBlank(sourceProfileCode)) {
                try {
                    WmsMaterial sourceMaterial = materialService.getByCode(sourceProfileCode);
                    if (sourceMaterial != null) {
                        materialVO.setColor(sourceMaterial.getColor());
                        log.debug("余料[{}]从源型材[{}]获取颜色信息: {}", 
                            surplusMaterial.getMaterialCode(), sourceProfileCode, sourceMaterial.getColor());
                    } else {
                        log.warn("未找到源型材[{}]信息，余料[{}]颜色信息为空", 
                            sourceProfileCode, surplusMaterial.getMaterialCode());
                    }
                } catch (Exception e) {
                    log.error("获取源型材[{}]颜色信息失败: {}", sourceProfileCode, e.getMessage());
                }
            }
            
            materialVO.setUnit("根"); // 余料单位固定为根
            materialVO.setPlanQuantity(new BigDecimal(surplusMaterial.getNum() != null ? surplusMaterial.getNum() : "1"));
            materialVO.setUnitCost(surplusMaterial.getUnitCost());
            
            // 设置分配的库位信息
            materialVO.setPlanWarehouseId(selectedWarehouseId);
            materialVO.setPlanWarehouseName(selectedWarehouseName);
            materialVO.setPlanLocationId(selectedLocationId);
            materialVO.setPlanLocationName(selectedLocationName);
            
            // 设置余料特有属性
            materialVO.setSurplusLength(surplusMaterial.getSurplusLength());
            materialVO.setSourceMaterialCode(surplusMaterial.getProfileCode());//原型材编号
            
            log.debug("余料[{}]库位分配成功: 仓库[{}], 库位[{}]", 
                surplusMaterial.getMaterialCode(), selectedWarehouseName, selectedLocationName);
            
            return materialVO;
            
        } catch (Exception e) {
            log.error("为余料[{}]分配库位失败", surplusMaterial.getMaterialCode(), e);
            throw new JeecgBootException("为余料分配库位失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<String> getSurplusWarehouseIds() {
        try {
            // 查询余料专用仓库（仓库名称包含"余料"或仓库类型为余料专用）
            LambdaQueryWrapper<WmsWarehouse> query = new LambdaQueryWrapper<>();
            query.eq(WmsWarehouse::getStatus, "0").eq(WmsWarehouse::getWarehouseType, "5");
            
            List<WmsWarehouse> surplusWarehouses = warehouseMapper.selectList(query);
            
            List<String> warehouseIds = surplusWarehouses.stream()
                .map(WmsWarehouse::getId)
                .collect(Collectors.toList());
            
            log.debug("找到{}个余料专用仓库", warehouseIds.size());
            return warehouseIds;
            
        } catch (Exception e) {
            log.error("获取余料专用仓库失败", e);
            return new ArrayList<>();
        }
    }
    
    @Override
    public List<String> getAvailableLocationIds(String warehouseId, String materialType) {
        if (StringUtils.isBlank(warehouseId)) {
            return new ArrayList<>();
        }
        
        try {
            // 查询可用库位（状态为空闲或未满）
            LambdaQueryWrapper<WmsWarehouseLocation> query = new LambdaQueryWrapper<>();
            //仓库ID为warehouseID且状态为 1-空闲或2-占用

            query.eq(WmsWarehouseLocation::getWarehouseId, warehouseId)
                    .in(WmsWarehouseLocation::getStatus, 1,2);
            
            List<WmsWarehouseLocation> availableLocations = locationMapper.selectList(query);
            
            List<String> locationIds = availableLocations.stream()
                .map(WmsWarehouseLocation::getId)
                .collect(Collectors.toList());
            
            log.debug("仓库[{}]找到{}个可用库位", warehouseId, locationIds.size());
            return locationIds;
            
        } catch (Exception e) {
            log.error("获取仓库[{}]可用库位失败", warehouseId, e);
            return new ArrayList<>();
        }
    }
}
